﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel.Composition;
using System.Collections;

namespace PefStudio.Windows
{
    [Export(Contract, typeof(AbstractPad))]
    [Pad(Name = "Properties")]
    public partial class PropertyPad : AbstractPad, IPartImportsSatisfiedNotification
    {
        public const string Contract = "PefStudio.Windows.Pads.Properties";

        private static PropertyPad _instance;

        // an empty container used to reset the property grid
        readonly PropertyContainer _emptyContainer = new PropertyContainer(false);

        PropertyContainer _activeContainer;

        internal static PropertyContainer ActiveContainer
        {
            get { return _instance._activeContainer; }
        }

        void SetActiveContainer(PropertyContainer pc)
        {
            if (_activeContainer == pc)
                return;
            if (pc == null)
                pc = _emptyContainer;
            _activeContainer = pc;

            UpdateSelectedObjectIfActive(pc);
            UpdateSelectableIfActive(pc);
            //UpdatePropertyGridReplacementControl(pc);
        }

        public static PropertyGrid Grid
        {
            get
            {
                if (_instance == null)
                    return null;
                else
                    return _instance.propertyGrid;
            }
        }

        public static event PropertyValueChangedEventHandler PropertyValueChanged;
        public static event EventHandler SelectedObjectChanged;
        public static event SelectedGridItemChangedEventHandler SelectedGridItemChanged;

        public PropertyPad()
        {
            InitializeComponent();

            _instance = this;

            propertyGrid.SelectedObjectsChanged += delegate(object sender, EventArgs e)
            {
                if (SelectedObjectChanged != null)
                    SelectedObjectChanged(sender, e);
            };
            propertyGrid.SelectedGridItemChanged += delegate(object sender, SelectedGridItemChangedEventArgs e)
            {
                if (SelectedGridItemChanged != null)
                    SelectedGridItemChanged(sender, e);
            };

            propertyGrid.PropertyValueChanged += new PropertyValueChangedEventHandler(PropertyChanged);
        }

        void PropertyChanged(object sender, PropertyValueChangedEventArgs e)
        {
            OnPropertyValueChanged(sender, e);
        }

        void OnPropertyValueChanged(object sender, PropertyValueChangedEventArgs e)
        {
            if (PropertyValueChanged != null)
            {
                PropertyValueChanged(sender, e);
            }
        }

        internal static void UpdateSelectedObjectIfActive(PropertyContainer container)
        {
            if (_instance == null) return;
            if (_instance._activeContainer != container)
                return;
            //LoggingService.Debug("UpdateSelectedObjectIfActive");
            if (container.SelectedObjects != null)
                _instance.SetDesignableObjects(container.SelectedObjects);
            else
                _instance.SetDesignableObject(container.SelectedObject);
        }

        internal static void UpdateSelectableIfActive(PropertyContainer container)
        {
            if (_instance == null) return;
            if (_instance._activeContainer != container)
                return;
            //LoggingService.Debug("UpdateSelectableIfActive");
            _instance.SetSelectableObjects(container.SelectableObjects);
        }

        bool _inUpdate = false;
        void SetDesignableObject(object obj)
        {
            _inUpdate = true;
            propertyGrid.SelectedObject = obj;
            SelectedObjectsChanged();
            _inUpdate = false;
        }

        void SetDesignableObjects(object[] obj)
        {
            _inUpdate = true;
            propertyGrid.SelectedObjects = obj;
            SelectedObjectsChanged();
            _inUpdate = false;
        }

        void SetSelectableObjects(ICollection coll)
        {
            _inUpdate = true;
            try
            {
                //comboBox.Items.Clear();
                //if (coll != null)
                //{
                //    foreach (object obj in SortObjectsBySiteName(coll))
                //    {
                //        comboBox.Items.Add(obj);
                //    }
                //}
                SelectedObjectsChanged();
            }
            finally
            {
                _inUpdate = false;
            }
        }

        void SelectedObjectsChanged()
        {
            //if (grid.SelectedObjects != null && grid.SelectedObjects.Length == 1)
            //{
            //    for (int i = 0; i < comboBox.Items.Count; ++i)
            //    {
            //        if (grid.SelectedObject == comboBox.Items[i])
            //        {
            //            comboBox.SelectedIndex = i;
            //        }
            //    }
            //}
            //else
            //{
            //    comboBox.SelectedIndex = -1;
            //}
        }

        #region IPartImportsSatisfiedNotification Members

        public void OnImportsSatisfied()
        {
            MainWindow.ActiveDocumentChanged += new EventHandler(WorkBench_ActiveDocumentChanged);
            MainWindow.ActivePadChanged += new EventHandler(WorkBench_ActivePadChanged);
        }

        IHasPropertyContainer previousContent;
        void WorkBench_ActivePadChanged(object sender, EventArgs e)
        {
            var c = MainWindow.ActivePad as IHasPropertyContainer;
            if (c == null)
            {
                if (previousContent == null)
                {
                    c = MainWindow.ActiveDocument as IHasPropertyContainer;
                }
                else
                {
                    // if the previous content is no longer visible, we have to remove the active container
                    if (previousContent is AbstractFloatDocument && previousContent != MainWindow.ActiveDocument)
                    {
                        c = null;
                    }
                    else if (previousContent is AbstractPad && previousContent != MainWindow.ActivePad)
                    {
                        c = null;
                    }
                    else
                    {
                        c = previousContent;
                    }
                }
            }
            if (c != null)
                SetActiveContainer(c.PropertyContainer);
            else
                SetActiveContainer(null);
            previousContent = c;
        }

        void WorkBench_ActiveDocumentChanged(object sender, EventArgs e)
        {
            var c = MainWindow.ActiveDocument as IHasPropertyContainer;
            if (c == null)
            {
                if (previousContent == null)
                {
                    c = MainWindow.ActivePad as IHasPropertyContainer;
                }
                else
                {
                    // if the previous content is no longer visible, we have to remove the active container
                    if (previousContent is AbstractPad && previousContent != MainWindow.ActivePad)
                    {
                        c = null;
                    }
                    else if (previousContent is AbstractFloatDocument && previousContent != MainWindow.ActiveDocument)
                    {
                        c = null;
                    }
                    else
                    {
                        c = previousContent;
                    }
                }
            }
            if (c != null)
                SetActiveContainer(c.PropertyContainer);
            else
                SetActiveContainer(null);
            previousContent = c;
        }

        #endregion
    }
}
